namespace SimpleWebServices.Web.Mvc
{
    using System;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Threading;
    using System.Web;
    using System.Web.Mvc;
    using Moq;
    using SimpleWebServices;
    using Xunit;

    public sealed class ResourceControllerFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<ResourceController>()
                .DerivesFrom<Controller>()
                .IsAbstractBaseClass()
                .Implements<IControlResource>()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new ResourceControllerDerived());
        }

        [Fact]
        public void op_LanguageNegotiation()
        {
            CultureInfo culture = Thread.CurrentThread.CurrentUICulture;

            try
            {
                string location = "/test";

                var mock = new Mock<HttpContextBase>();
                mock.SetupGet<string>(x => x.Request.Path).Returns(location).Verifiable();
                mock.SetupGet<string>(x => x.Request.RawUrl).Returns(location).Verifiable();
                HttpContextFactory.Mock = mock.Object;

                SeeOtherResult result = new ResourceControllerDerived().LanguageNegotiation() as SeeOtherResult;

                Assert.Equal<string>(location + ".en", result.Location);

                mock.VerifyAll();
            }
            finally
            {
                Thread.CurrentThread.CurrentUICulture = culture;
            }
        }

        [Fact]
        public void op_ContentNegotiation_CultureInfo()
        {
            CultureInfo culture = Thread.CurrentThread.CurrentUICulture;

            try
            {
                string location = "/test.fr";

                NameValueCollection headers = new NameValueCollection();
                headers["Accept"] = "*/*, text/*, text/html";

                var mock = new Mock<HttpContextBase>();
                mock.SetupGet<NameValueCollection>(x => x.Request.Headers).Returns(headers).Verifiable();
                mock.SetupGet<string>(x => x.Request.Path).Returns(location).Verifiable();
                mock.SetupGet<string>(x => x.Request.RawUrl).Returns(location).Verifiable();
                HttpContextFactory.Mock = mock.Object;

                SeeOtherResult result = new ResourceControllerDerived().ContentNegotiation(new CultureInfo("fr")) as SeeOtherResult;

                Assert.Equal<string>(location + ".html", result.Location);

                mock.VerifyAll();
            }
            finally
            {
                Thread.CurrentThread.CurrentUICulture = culture;
            }
        }

        [Fact]
        public void op_ContentNegotiation_CultureInfoInvariantCulture()
        {
            CultureInfo culture = Thread.CurrentThread.CurrentUICulture;

            try
            {
                Assert.Throws<ArgumentOutOfRangeException>(() => new ResourceControllerDerived().ContentNegotiation(CultureInfo.InvariantCulture));
            }
            finally
            {
                Thread.CurrentThread.CurrentUICulture = culture;
            }
        }

        [Fact]
        public void op_ContentNegotiation_CultureInfoNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ResourceControllerDerived().ContentNegotiation(null as CultureInfo));
        }

        [Fact]
        public void op_View_CultureInfo_object()
        {
            CultureInfo culture = Thread.CurrentThread.CurrentUICulture;

            try
            {
                Assert.IsAssignableFrom<ViewResult>(new ResourceControllerDerived().View(new CultureInfo("fr"), DateTime.UtcNow));
            }
            finally
            {
                Thread.CurrentThread.CurrentUICulture = culture;
            }
        }

        [Fact]
        public void op_View_CultureInfoInvariantCulture_object()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => new ResourceControllerDerived().View(CultureInfo.InvariantCulture, DateTime.UtcNow));
        }

        [Fact]
        public void op_View_CultureInfoNull_object()
        {
            CultureInfo culture = Thread.CurrentThread.CurrentUICulture;

            try
            {
                Assert.Throws<ArgumentNullException>(() => new ResourceControllerDerived().View(null as CultureInfo, DateTime.UtcNow));
            }
            finally
            {
                Thread.CurrentThread.CurrentUICulture = culture;
            }
        }

        [Fact]
        public void op_View_CultureInfo_objectNull()
        {
            CultureInfo culture = Thread.CurrentThread.CurrentUICulture;

            try
            {
                Assert.IsAssignableFrom<ViewResult>(new ResourceControllerDerived().View(new CultureInfo("fr"), null as object));
            }
            finally
            {
                Thread.CurrentThread.CurrentUICulture = culture;
            }
        }
    }
}